package com.innerchic.mapper.database;

import android.database.sqlite.SQLiteDatabase;

import com.innerchic.mapper.database.annotation.DatabaseTable;
import com.innerchic.mapper.database.annotation.InTable;
import com.innerchic.mapper.database.annotation.Insignificance;
import com.innerchic.mapper.database.annotation.PrimaryKey;

import java.lang.reflect.Field;
import java.util.List;

/**
 * ================================================
 * 作    者：贾恒飞 >>> 17515250730@163.com
 * 项    目：young
 * 日    期：2021/11/3 14:32
 * 包    名：com.innerchic.mapper.database
 * 描    述：便捷的数据库操作方式
 * Create by zFox from AndroidStudio4.2
 * ================================================
 */
public class FastDatabase {

    /**
     * 当前所持有的数据库对象
     */
    public final SQLiteDatabase db;

    /**
     * 当前对象包含一个sqlit数据库对象,期望是一个读写数据库
     *
     * @param db 数据库对象
     */
    private FastDatabase(SQLiteDatabase db) {
        this.db = db;
    }

    /**
     * 关闭当前方法
     */
    public void close() {
        if (this.db != null) {
            this.db.close();
        }
    }

    /**
     * 在外部创建一个数据库包装类
     *
     * @param wdb 期望是一个可读写数据库
     * @return 一个数据库包装对象
     */
    public static FastDatabase createDatabase(SQLiteDatabase wdb) {
        return new FastDatabase(wdb);
    }

    /**
     * 当前提供的默认的数据库对象
     */
    private static FastDatabase defaultFastDatabase;

    /**
     * 获取当前默认的单例数据库对象
     *
     * @return 如果没有初始化过, 会返回null
     */
    public static FastDatabase getInstance() {
        return defaultFastDatabase;
    }

    /**
     * 初始化当前默认数据库
     *
     * @param wdb 读写数据库对象
     */
    public static synchronized void initDefaultDatabase(SQLiteDatabase wdb) {
        if (defaultFastDatabase != null) {
            defaultFastDatabase.close();
            defaultFastDatabase = null;
        }
        defaultFastDatabase = new FastDatabase(wdb);
    }


    /**
     * 数据库查询帮助类
     *
     * @param <Bean> 泛型对象
     */
    public final static class DbHelper<Bean> {

        /**
         * 当前实例对象
         */
        private final SQLiteDatabase db;

        /**
         * 当前实例类型
         */
        private final Class<Bean> nowClass;

        /**
         * 表名
         */
        private String table = "";

        /**
         * 主键字符串
         */
        private String primaryKeyString = "";


        /**
         * 构造参数
         *
         * @param nowClass 当前类型
         * @param wdb      读写数据库
         */
        public DbHelper(Class<Bean> nowClass, SQLiteDatabase wdb) {
            this.nowClass = nowClass;
            this.db = wdb;
            //获取表名
            DatabaseTable annotation = nowClass.getAnnotation(DatabaseTable.class);
            if (annotation != null) {
                table = annotation.value();
            }
            //获取主键
            Field[] fields = nowClass.getDeclaredFields();
            for (Field field : fields) {
                PrimaryKey primaryKey = field.getAnnotation(PrimaryKey.class);
                if (primaryKey == null) {
                    continue;
                }
                InTable inTable = field.getAnnotation(InTable.class);
                if (inTable != null) {
                    primaryKeyString = inTable.value();
                }
                break;
            }
        }

        //查询条件
        private String where = "";//条件语句
        private String[] whereValue = null;//条件语句参数
        private String[] columns = null;//列数
        private String groupBy = null;//分组
        private String having = null;//having
        private String orderBy = null;//排序
        private String limit = null;//例"6,9":第6行开始,返回9行数据
        private String condition = null;//条件,插在主句与其他条件之间

        /**
         * 设置查询条件where
         *
         * @param where 查询语句
         */
        public DbHelper<Bean> where(String where) {
            this.where = where;
            return this;
        }

        /**
         * 设置查询条件参数
         *
         * @param whereValue 查询语句参数
         */
        public DbHelper<Bean> whereValue(String[] whereValue) {
            this.whereValue = whereValue;
            return this;
        }

        /**
         * 设置查询的列集合
         *
         * @param columns 列集合
         */
        public DbHelper<Bean> columns(String[] columns) {
            this.columns = columns;
            return this;
        }

        /**
         * 设置分组集合
         *
         * @param groupBy 分组
         */
        public DbHelper<Bean> groupBy(String groupBy) {
            this.groupBy = groupBy;
            return this;
        }

        /**
         * having
         *
         * @param having having
         */
        public DbHelper<Bean> having(String having) {
            this.having = having;
            return this;
        }

        /**
         * 设置排序
         *
         * @param orderBy 排序 desc降序,asc升序
         */
        public DbHelper<Bean> orderBy(String orderBy) {
            this.orderBy = orderBy;
            return this;
        }

        /**
         * 设置分页
         *
         * @param limit 分页
         */
        public DbHelper<Bean> limit(String limit) {
            this.limit = limit;
            return this;
        }

        /**
         * 设置分页
         *
         * @param begin 开始页码
         * @param size  长度
         */
        public DbHelper<Bean> limit(int begin, int size) {
            this.limit = begin + "," + size;
            return this;
        }

        /**
         * 拼接id条件
         *
         * @param id 主键id
         */
        public DbHelper<Bean> id(int id) {
            this.where = primaryKeyString + " = ? ";
            this.whereValue = new String[]{String.valueOf(id)};
            return this;
        }

        /**
         * 设置条件
         *
         * @param condition 条件语句
         */
        public DbHelper<Bean> condition(String condition) {
            this.condition = condition;
            return this;
        }

        /**
         * 增量修改一个字段+1
         *
         * @param column 字段列名
         */
        public void incremental(String column) {
            incremental(column, 1);
        }

        /**
         * 增量修改一个字段
         *
         * @param column  字段列名
         * @param addLong 增量大小
         */
        public void incremental(String column, int addLong) {
            String sql = "update " + this.table + " set " + column + " = " + column + " + ?";
            if (this.where != null) {
                sql = sql + " where " + this.where;
            }
            String[] params;
            if (this.whereValue != null) {
                params = new String[this.whereValue.length + 1];
                params[0] = String.valueOf(addLong);
                int index = 1;
                for (String s : this.whereValue) {
                    params[index] = s;
                    index++;
                }
            } else {
                params = new String[]{String.valueOf(addLong)};
            }
            this.db.execSQL(sql, params);
        }

        /**
         * 是否存在
         *
         * @return true存在
         */
        public boolean exist() {
            String sql = "select count from " + this.table + " where " + this.where;
            return DatabaseOperation.exist(db, sql, whereValue);
        }

        /**
         * 查询
         */
        public List<Bean> query() {
            return DatabaseOperation.query(db, nowClass, table, columns, where, whereValue, groupBy, having, orderBy, limit);
        }

        /**
         * 查询
         * 当前查询的where语句代指整个sql语句
         * whereValue指整个sql语句的参数
         */
        public List<Bean> rawQuery() {
            return DatabaseOperation.rawQuery(db, nowClass, where, whereValue);
        }

        /**
         * 查询一个
         */
        public Bean queryOne() {
            List<Bean> query = DatabaseOperation.query(db, nowClass, table, columns, where, whereValue, groupBy, having, orderBy, null);
            if (query.size() == 0) return null;
            return query.get(0);
        }

        /**
         * 更新
         *
         * @param t 对象
         * @return 更新的条数,-1为报错
         */
        public int update(Bean t) {
            return DatabaseOperation.update(db, t, table, where, whereValue, true);
        }

        /**
         * 更新
         *
         * @param t           对象
         * @param isExcludeId 是否排除主键,默认true,不会修改<Bean>中的主键值
         * @return 更新的条数,-1为报错
         */
        public int update(Bean t, boolean isExcludeId) {
            return DatabaseOperation.update(db, t, table, where, whereValue, isExcludeId);
        }

        /**
         * 根据ID修改
         *
         * @param t 对象
         * @return 更新的条数,-1为报错
         */
        public int updateById(Bean t) {
            Field[] fields = t.getClass().getDeclaredFields();
            for (Field field : fields) {
                Insignificance insignificance = field.getAnnotation(Insignificance.class);
                if (insignificance != null) {
                    continue;
                }
                PrimaryKey annotation = field.getAnnotation(PrimaryKey.class);
                if (annotation == null) {
                    continue;
                }
                InTable inTable = field.getAnnotation(InTable.class);
                String idName = null;
                if (inTable != null) {
                    idName = inTable.value();
                }
                if (idName == null) idName = field.getName();
                where = idName + " = ? ";
                try {
                    field.setAccessible(true);
                    whereValue = new String[]{String.valueOf(field.get(t))};
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            return DatabaseOperation.update(db, t, table, where, whereValue, true);
        }

        /**
         * 修改一处字段
         *
         * @param key   字段名
         * @param value 值
         * @return 修改的条数
         */
        public int update(String key, Object value) {
            return DatabaseOperation.update(db, table, key, value, where, whereValue);
        }

        /**
         * 删除
         */
        public int delete() {
            return DatabaseOperation.delete(db, table, where, whereValue);
        }

        /**
         * 插入一条数据
         *
         * @param t              数据对象
         * @param nullColumnHack 空列
         * @return 添加的id
         */
        public long insert(Bean t, String... nullColumnHack) {
            String nullColumn = null;
            if (nullColumnHack != null && nullColumnHack.length > 0) {
                nullColumn = nullColumnHack[0];
            }
            return DatabaseOperation.insert(db, t, table, nullColumn);
        }

        /**
         * 执行sql
         *
         * @param sql sql语句
         */
        public void execSQL(String sql) {
            db.execSQL(sql);
        }

    }

}
